/******************************************************************************
  A simple program of Hisilicon HI3518 audio input/output/encoder/decoder implementation.
  Copyright (C), 2010-2011, Hisilicon Tech. Co., Ltd.
 ******************************************************************************
Modification:  2012-7-2 Created
 ******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>

#include "sample_comm.h"
#include "mytest.h"
#include "acodec.h"


#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* End of #ifdef __cplusplus */

#define ACODEC_FILE     "/dev/acodec"

#define AUDIO_ADPCM_TYPE ADPCM_TYPE_DVI4/* ADPCM_TYPE_IMA, ADPCM_TYPE_DVI4*/
#define G726_BPS MEDIA_G726_40K         /* MEDIA_G726_16K, MEDIA_G726_24K ... */

typedef struct tagSAMPLE_AENC_S
{
	HI_BOOL bStart;
	pthread_t stAencPid;
	HI_S32  AeChn;
	HI_S32  AdChn;
	FILE    *pfd;
	HI_BOOL bSendAdChn;
} SAMPLE_AENC_S;

typedef struct tagSAMPLE_AI_S
{
	HI_BOOL bStart;
	HI_S32  AiDev;
	HI_S32  AiChn;
	HI_S32  AencChn;
	HI_S32  AoDev;
	HI_S32  AoChn;
	HI_BOOL bSendAenc;
	HI_BOOL bSendAo;
	pthread_t stAiPid;
} SAMPLE_AI_S;

typedef struct tagSAMPLE_ADEC_S
{
	HI_BOOL bStart;
	HI_S32 AdChn; 
	FILE *pfd;
	pthread_t stAdPid;
} SAMPLE_ADEC_S;

static SAMPLE_AI_S gs_stSampleAi[AI_DEV_MAX_NUM*AIO_MAX_CHN_NUM];
static SAMPLE_AENC_S gs_stSampleAenc[AENC_MAX_CHN_NUM];
static SAMPLE_ADEC_S gs_stSampleAdec[ADEC_MAX_CHN_NUM];

/******************************************************************************
 * function : get frame from Ai, send it  to Aenc or Ao
 ******************************************************************************/
void *SAMPLE_COMM_AUDIO_AiProc(void *parg)
{
	HI_S32 s32Ret;
	HI_S32 AiFd;
	SAMPLE_AI_S *pstAiCtl = (SAMPLE_AI_S *)parg;
	AUDIO_FRAME_S stFrame; 
	fd_set read_fds;
	struct timeval TimeoutVal;
	AI_CHN_PARAM_S stAiChnPara;

	s32Ret = HI_MPI_AI_GetChnParam(pstAiCtl->AiDev, pstAiCtl->AiChn, &stAiChnPara);
	if (HI_SUCCESS != s32Ret)
	{
		printf("%s: Get ai chn param failed\n", __FUNCTION__);
		return NULL;
	}

	stAiChnPara.u32UsrFrmDepth = 30;

	s32Ret = HI_MPI_AI_SetChnParam(pstAiCtl->AiDev, pstAiCtl->AiChn, &stAiChnPara);
	if (HI_SUCCESS != s32Ret)
	{
		printf("%s: set ai chn param failed\n", __FUNCTION__);
		return NULL;
	}

	FD_ZERO(&read_fds);
	AiFd = HI_MPI_AI_GetFd(pstAiCtl->AiDev, pstAiCtl->AiChn);
	FD_SET(AiFd,&read_fds);

	while (pstAiCtl->bStart)
	{     
		TimeoutVal.tv_sec = 1;
		TimeoutVal.tv_usec = 0;

		FD_ZERO(&read_fds);
		FD_SET(AiFd,&read_fds);

		s32Ret = select(AiFd+1, &read_fds, NULL, NULL, &TimeoutVal);
		if (s32Ret < 0) 
		{
			break;
		}
		else if (0 == s32Ret) 
		{
			printf("%s: get ai frame select time out\n", __FUNCTION__);
			break;
		}        

		if (FD_ISSET(AiFd, &read_fds))
		{
			/* get frame from ai chn */
			s32Ret = HI_MPI_AI_GetFrame(pstAiCtl->AiDev, pstAiCtl->AiChn,
					&stFrame, NULL, HI_FALSE);
			if (HI_SUCCESS != s32Ret )
			{
				printf("%s: HI_MPI_AI_GetFrame(%d, %d), failed with %#x!\n",\
						__FUNCTION__, pstAiCtl->AiDev, pstAiCtl->AiChn, s32Ret);
				pstAiCtl->bStart = HI_FALSE;
				return NULL;
			}

			/* send frame to encoder */
			if (HI_TRUE == pstAiCtl->bSendAenc)
			{
				HI_MPI_AENC_SendFrame(pstAiCtl->AencChn, &stFrame, NULL);
			}

			/* send frame to ao */
			if (HI_TRUE == pstAiCtl->bSendAo)
			{
				HI_MPI_AO_SendFrame(pstAiCtl->AoDev, pstAiCtl->AoChn,
						&stFrame, HI_TRUE);
			}

			/* finally you must release the stream */
			HI_MPI_AI_ReleaseFrame(pstAiCtl->AiDev, pstAiCtl->AiChn,
					&stFrame, NULL);
		}
	}

	pstAiCtl->bStart = HI_FALSE;
	return NULL;
}

/******************************************************************************
 * function : get stream from Aenc, send it  to Adec & save it to file
 ******************************************************************************/
void *SAMPLE_COMM_AUDIO_AencProc(void *parg)
{
	HI_S32 s32Ret;
	HI_S32 AencFd;
	SAMPLE_AENC_S *pstAencCtl = (SAMPLE_AENC_S *)parg;
	AUDIO_STREAM_S stStream;
	fd_set read_fds;
	struct timeval TimeoutVal;

	FD_ZERO(&read_fds);    
	AencFd = HI_MPI_AENC_GetFd(pstAencCtl->AeChn);
	FD_SET(AencFd, &read_fds);

	while (pstAencCtl->bStart)
	{     
		TimeoutVal.tv_sec = 1;
		TimeoutVal.tv_usec = 0;

		FD_ZERO(&read_fds);
		FD_SET(AencFd,&read_fds);

		s32Ret = select(AencFd+1, &read_fds, NULL, NULL, &TimeoutVal);
		if (s32Ret < 0) 
		{
			break;
		}
		else if (0 == s32Ret) 
		{
			printf("%s: get aenc stream select time out\n", __FUNCTION__);
			break;
		}

		if (FD_ISSET(AencFd, &read_fds))
		{
			/* get stream from aenc chn */
			s32Ret = HI_MPI_AENC_GetStream(pstAencCtl->AeChn, &stStream, HI_FALSE);
			if (HI_SUCCESS != s32Ret )
			{
				printf("%s: HI_MPI_AENC_GetStream(%d), failed with %#x!\n",\
						__FUNCTION__, pstAencCtl->AeChn, s32Ret);
				pstAencCtl->bStart = HI_FALSE;
				return NULL;
			}

			/* send stream to decoder and play for testing */
			if (HI_TRUE == pstAencCtl->bSendAdChn)
			{
				//HI_MPI_ADEC_SendStream(pstAencCtl->AdChn, &stStream, HI_TRUE);
			}

			//printf("---------write-----------a frame\r\n");        
			/* save audio stream to file */
			//fwrite(stStream.pStream,1,stStream.u32Len, pstAencCtl->pfd);

			BUFFERDATA_t *pTMP = create_myfifo();
			pTMP->buf = (char *)malloc(stStream.u32Len);
			if (pTMP->buf == NULL)
			{
				perror("out of mem\r\n");
			}
			memcpy(pTMP->buf, stStream.pStream, stStream.u32Len);
			pTMP->size = stStream.u32Len;
			pTMP->ftype = 0;
			add_audio(pTMP);

			/* finally you must release the stream */
			HI_MPI_AENC_ReleaseStream(pstAencCtl->AeChn, &stStream);
		}    
	}

	fclose(pstAencCtl->pfd);
	pstAencCtl->bStart = HI_FALSE;
	return NULL;
}

/******************************************************************************
 * function : get stream from file, and send it  to Adec
 ******************************************************************************/
void *SAMPLE_COMM_AUDIO_AdecProc(void *parg)
{
	HI_S32 s32Ret;
	AUDIO_STREAM_S stAudioStream;    
	HI_U32 u32Len = 640;
	HI_U32 u32ReadLen;
	HI_S32 s32AdecChn;
	HI_U8 *pu8AudioStream = NULL;
	SAMPLE_ADEC_S *pstAdecCtl = (SAMPLE_ADEC_S *)parg;    
	FILE *pfd = pstAdecCtl->pfd;
	s32AdecChn = pstAdecCtl->AdChn;

	pu8AudioStream = (HI_U8*)malloc(sizeof(HI_U8)*MAX_AUDIO_STREAM_LEN);
	if (NULL == pu8AudioStream)
	{
		printf("%s: malloc failed!\n", __FUNCTION__);
		return NULL;
	}

	while (HI_TRUE == pstAdecCtl->bStart)
	{
		/* read from file */
		stAudioStream.pStream = pu8AudioStream;
		u32ReadLen = fread(stAudioStream.pStream, 1, u32Len, pfd);
		if (u32ReadLen <= 0)
		{            
			fseek(pfd, 0, SEEK_SET);/*read file again*/
			continue;
		}

		/* here only demo adec streaming sending mode, but pack sending mode is commended */
		stAudioStream.u32Len = u32ReadLen;
		s32Ret = HI_MPI_ADEC_SendStream(s32AdecChn, &stAudioStream, HI_TRUE);
		if (s32Ret)
		{
			printf("%s: HI_MPI_ADEC_SendStream(%d) failed with %#x!\n",\
					__FUNCTION__, s32AdecChn, s32Ret);
			break;
		}
	}

	free(pu8AudioStream);
	pu8AudioStream = NULL;
	fclose(pfd);
	pstAdecCtl->bStart = HI_FALSE;
	return NULL;
}

/******************************************************************************
 * function : Create the thread to get frame from ai and send to ao
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_CreatTrdAiAo(AUDIO_DEV AiDev, AI_CHN AiChn, AUDIO_DEV AoDev, AO_CHN AoChn)
{
	SAMPLE_AI_S *pstAi = NULL;

	pstAi = &gs_stSampleAi[AiDev*AIO_MAX_CHN_NUM + AiChn];
	pstAi->bSendAenc = HI_FALSE;
	pstAi->bSendAo = HI_TRUE;
	pstAi->bStart= HI_TRUE;
	pstAi->AiDev = AiDev;
	pstAi->AiChn = AiChn;
	pstAi->AoDev = AoDev;
	pstAi->AoChn = AoChn;

	pthread_create(&pstAi->stAiPid, 0, SAMPLE_COMM_AUDIO_AiProc, pstAi);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Create the thread to get frame from ai and send to aenc
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_CreatTrdAiAenc(AUDIO_DEV AiDev, AI_CHN AiChn, AENC_CHN AeChn)
{
	SAMPLE_AI_S *pstAi = NULL;

	pstAi = &gs_stSampleAi[AiDev*AIO_MAX_CHN_NUM + AiChn];
	pstAi->bSendAenc = HI_TRUE;
	pstAi->bSendAo = HI_FALSE;
	pstAi->bStart= HI_TRUE;
	pstAi->AiDev = AiDev;
	pstAi->AiChn = AiChn;
	pstAi->AencChn = AeChn;
	pthread_create(&pstAi->stAiPid, 0, SAMPLE_COMM_AUDIO_AiProc, pstAi);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Create the thread to get stream from aenc and send to adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_CreatTrdAencAdec(AENC_CHN AeChn, ADEC_CHN AdChn, FILE *pAecFd)
{
	SAMPLE_AENC_S *pstAenc = NULL;

	if (NULL == pAecFd)
	{
		return HI_FAILURE;
	}

	pstAenc = &gs_stSampleAenc[AeChn];
	pstAenc->AeChn = AeChn;
	pstAenc->AdChn = AdChn;
	pstAenc->bSendAdChn = HI_TRUE;
	pstAenc->pfd = pAecFd;    
	pstAenc->bStart = HI_TRUE;    
	pthread_create(&pstAenc->stAencPid, 0, SAMPLE_COMM_AUDIO_AencProc, pstAenc);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Create the thread to get stream from file and send to adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_CreatTrdFileAdec(ADEC_CHN AdChn, FILE *pAdcFd)
{
	SAMPLE_ADEC_S *pstAdec = NULL;

	if (NULL == pAdcFd)
	{
		return HI_FAILURE;
	}

	pstAdec = &gs_stSampleAdec[AdChn];
	pstAdec->AdChn = AdChn;
	pstAdec->pfd = pAdcFd;
	pstAdec->bStart = HI_TRUE;
	pthread_create(&pstAdec->stAdPid, 0, SAMPLE_COMM_AUDIO_AdecProc, pstAdec);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Destory the thread to get frame from ai and send to ao or aenc
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_DestoryTrdAi(AUDIO_DEV AiDev, AI_CHN AiChn)
{
	SAMPLE_AI_S *pstAi = NULL;

	pstAi = &gs_stSampleAi[AiDev*AIO_MAX_CHN_NUM + AiChn];
	pstAi->bStart= HI_FALSE;
	pthread_join(pstAi->stAiPid, 0);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Destory the thread to get stream from aenc and send to adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_DestoryTrdAencAdec(AENC_CHN AeChn)
{
	SAMPLE_AENC_S *pstAenc = NULL;

	pstAenc = &gs_stSampleAenc[AeChn];
	pstAenc->bStart = HI_FALSE;
	pthread_join(pstAenc->stAencPid, 0);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Destory the thread to get stream from file and send to adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_DestoryTrdFileAdec(ADEC_CHN AdChn)
{
	SAMPLE_ADEC_S *pstAdec = NULL;

	pstAdec = &gs_stSampleAdec[AdChn];
	pstAdec->bStart = HI_FALSE;
	pthread_join(pstAdec->stAdPid, 0);

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Ao bind Adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_AoBindAdec(AUDIO_DEV AoDev, AO_CHN AoChn, ADEC_CHN AdChn)
{
	MPP_CHN_S stSrcChn,stDestChn;

	stSrcChn.enModId = HI_ID_ADEC;
	stSrcChn.s32DevId = 0;
	stSrcChn.s32ChnId = AdChn;
	stDestChn.enModId = HI_ID_AO;
	stDestChn.s32DevId = AoDev;
	stDestChn.s32ChnId = AoChn;

	return HI_MPI_SYS_Bind(&stSrcChn, &stDestChn); 
}

/******************************************************************************
 * function : Ao unbind Adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_AoUnbindAdec(AUDIO_DEV AoDev, AO_CHN AoChn, ADEC_CHN AdChn)
{
	MPP_CHN_S stSrcChn,stDestChn;

	stSrcChn.enModId = HI_ID_ADEC;
	stSrcChn.s32ChnId = AdChn;
	stSrcChn.s32DevId = 0;
	stDestChn.enModId = HI_ID_AO;
	stDestChn.s32DevId = AoDev;
	stDestChn.s32ChnId = AoChn;

	return HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn); 
}

/******************************************************************************
 * function : Ao bind Ai
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_AoBindAi(AUDIO_DEV AiDev, AI_CHN AiChn, AUDIO_DEV AoDev, AO_CHN AoChn)
{
	MPP_CHN_S stSrcChn,stDestChn;

	stSrcChn.enModId = HI_ID_AI;
	stSrcChn.s32ChnId = AiChn;
	stSrcChn.s32DevId = AiDev;
	stDestChn.enModId = HI_ID_AO;
	stDestChn.s32DevId = AoDev;
	stDestChn.s32ChnId = AoChn;

	return HI_MPI_SYS_Bind(&stSrcChn, &stDestChn); 
}

/******************************************************************************
 * function : Ao unbind Ai
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_AoUnbindAi(AUDIO_DEV AiDev, AI_CHN AiChn, AUDIO_DEV AoDev, AO_CHN AoChn)
{
	MPP_CHN_S stSrcChn,stDestChn;

	stSrcChn.enModId = HI_ID_AI;
	stSrcChn.s32ChnId = AiChn;
	stSrcChn.s32DevId = AiDev;
	stDestChn.enModId = HI_ID_AO;
	stDestChn.s32DevId = AoDev;
	stDestChn.s32ChnId = AoChn;

	return HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn); 
}

/******************************************************************************
 * function : Aenc bind Ai
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_AencBindAi(AUDIO_DEV AiDev, AI_CHN AiChn, AENC_CHN AeChn)
{
	MPP_CHN_S stSrcChn,stDestChn;

	stSrcChn.enModId = HI_ID_AI;
	stSrcChn.s32DevId = AiDev;
	stSrcChn.s32ChnId = AiChn;
	stDestChn.enModId = HI_ID_AENC;
	stDestChn.s32DevId = 0;
	stDestChn.s32ChnId = AeChn;

	return HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
}

/******************************************************************************
 * function : Aenc unbind Ai
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_AencUnbindAi(AUDIO_DEV AiDev, AI_CHN AiChn, AENC_CHN AeChn)
{
	MPP_CHN_S stSrcChn,stDestChn;

	stSrcChn.enModId = HI_ID_AI;
	stSrcChn.s32DevId = AiDev;
	stSrcChn.s32ChnId = AiChn;
	stDestChn.enModId = HI_ID_AENC;
	stDestChn.s32DevId = 0;
	stDestChn.s32ChnId = AeChn;

	return HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn);      
}

/******************************************************************************
 * function : Acodec config [ s32Samplerate(0:8k, 1:16k ) ]
 ******************************************************************************/
HI_S32 SAMPLE_Acodec_CfgAudio(AUDIO_SAMPLE_RATE_E enSample, HI_BOOL bMicIn)
{
	HI_S32 fdAcodec = -1;
	unsigned int i2s_fs_sel = 0;
	unsigned int mixer_mic_ctrl = 0;
	unsigned int gain_mic = 0;

	fdAcodec = open(ACODEC_FILE,O_RDWR);
	if (fdAcodec < 0)
	{
		printf("%s: can't open acodec,%s\n", __FUNCTION__, ACODEC_FILE);
		return HI_FAILURE;     
	}

	if(ioctl(fdAcodec, ACODEC_SOFT_RESET_CTRL))
	{
		printf("Reset audio codec error\n");
		close(fdAcodec);
		return HI_FAILURE;
	}

	if ((AUDIO_SAMPLE_RATE_8000 == enSample)
			|| (AUDIO_SAMPLE_RATE_11025 == enSample)
			|| (AUDIO_SAMPLE_RATE_12000 == enSample))
	{
		i2s_fs_sel = 0x18;
	}
	else if ((AUDIO_SAMPLE_RATE_16000 == enSample)
			|| (AUDIO_SAMPLE_RATE_22050 == enSample)
			|| (AUDIO_SAMPLE_RATE_24000 == enSample))
	{
		i2s_fs_sel = 0x19;
	}
	else if ((AUDIO_SAMPLE_RATE_32000 == enSample)
			|| (AUDIO_SAMPLE_RATE_44100 == enSample)
			|| (AUDIO_SAMPLE_RATE_48000 == enSample))
	{
		i2s_fs_sel = 0x1a;
	}
	else 
	{
		printf("%s: not support enSample:%d\n", __FUNCTION__, enSample);
		close(fdAcodec);
		return HI_FAILURE;
	}

	if (ioctl(fdAcodec, ACODEC_SET_I2S1_FS, &i2s_fs_sel))
	{
		printf("%s: set acodec sample rate failed\n", __FUNCTION__);
		close(fdAcodec);
		return HI_FAILURE;
	}

	if (HI_TRUE == bMicIn)
	{
		/*do not select micin */  
#if 0
		mixer_mic_ctrl = 1;
		if (ioctl(fdAcodec, ACODEC_SET_MIXER_MIC, &mixer_mic_ctrl))
		{
			printf("%s: set acodec micin failed\n", __FUNCTION__);
			close(fdAcodec);
			return HI_FAILURE;
		}
#endif		
		/* set volume plus (0~0x1f,default 0x0c) */

		printf("----------------->>>>>>>>.\r\n");
		gain_mic = 0x1f;
		if (ioctl(fdAcodec, ACODEC_SET_GAIN_MICL, &gain_mic))
		{
			printf("%s: set acodec micin volume failed\n", __FUNCTION__);
			close(fdAcodec);
			return HI_FAILURE;
		}

		if (ioctl(fdAcodec, ACODEC_SET_GAIN_MICR, &gain_mic))
		{
			printf("%s: set acodec micin volume failed\n", __FUNCTION__);
			close(fdAcodec);
			return HI_FAILURE;
		}

		ACODEC_VOL_CTRL vol_ctrl;

		vol_ctrl.vol_ctrl_mute = 0x0;
		vol_ctrl.vol_ctrl = 0x30;
		printf("set L vol =%d\r\n", vol_ctrl.vol_ctrl);
		ioctl(fdAcodec, ACODEC_SET_DACL_VOL, &vol_ctrl);
		if (ioctl(fdAcodec, ACODEC_SET_DACR_VOL, &vol_ctrl))
		{
			printf("error\r\n");
		}

		vol_ctrl.vol_ctrl_mute = 0x0;
		vol_ctrl.vol_ctrl = 0x40;
		int r = ioctl(fdAcodec, ACODEC_SET_ADCL_VOL, &vol_ctrl);
		printf("r=%d\r\n", r);
		r = ioctl(fdAcodec, ACODEC_SET_ADCR_VOL, &vol_ctrl);
		printf("r=%d\r\n", r);

		int vol;
		vol = 62;
		//ioctl(fdAcodec, ACODEC_SET_OUTPUT_VOL, &vol);
		printf("out vol=%d\r\n", vol);


		//ioctl(fdAcodec, ACODEC_GET_INPUT_VOL, &vol);
		vol = 62;
		//ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &vol);
		printf("in vol=%d\r\n", vol);



	}
	close(fdAcodec);    

	return HI_SUCCESS;
}

HI_S32 SAMPLE_COMM_AUDIO_CfgAcodec(AIO_ATTR_S *pstAioAttr, HI_BOOL bMacIn)
{
	HI_S32 s32Ret = HI_FAILURE;

	s32Ret = SAMPLE_Acodec_CfgAudio(pstAioAttr->enSamplerate, bMacIn);
	return s32Ret;
}

/******************************************************************************
 * function : Start Ai
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StartAi(AUDIO_DEV AiDevId, HI_S32 s32AiChnCnt,
		AIO_ATTR_S *pstAioAttr, HI_BOOL bAnrEn, AUDIO_RESAMPLE_ATTR_S *pstAiReSmpAttr)
{
	HI_S32 i, s32Ret;

	s32Ret = HI_MPI_AI_SetPubAttr(AiDevId, pstAioAttr);
	if (s32Ret)
	{
		printf("%s: HI_MPI_AI_SetPubAttr(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
		return HI_FAILURE;
	}
	if (HI_MPI_AI_Enable(AiDevId))
	{
		printf("%s: HI_MPI_AI_Enable(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
		return HI_FAILURE;
	}                
	for (i=0; i<s32AiChnCnt; i++)
	{
		if (HI_MPI_AI_EnableChn(AiDevId, i))
		{
			printf("%s: HI_MPI_AI_EnableChn(%d,%d) failed with %#x\n", __FUNCTION__,\
					AiDevId, i, s32Ret);
			return HI_FAILURE;
		}

		if (HI_TRUE == bAnrEn)
		{
			if (HI_MPI_AI_EnableAnr(AiDevId, i))
			{
				printf("%s: HI_MPI_AI_EnableAnr(%d,%d) failed with %#x\n", __FUNCTION__,\
						AiDevId, i, s32Ret);
				return HI_FAILURE;
			}
		}

		if (NULL != pstAiReSmpAttr)
		{
			if (HI_MPI_AI_EnableReSmp(AiDevId, i, pstAiReSmpAttr))
			{
				printf("%s: HI_MPI_AI_EnableReSmp(%d,%d) failed with %#x\n",\
						__FUNCTION__, AiDevId, i, s32Ret);
				return HI_FAILURE;
			}
		}
	}

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Stop Ai
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StopAi(AUDIO_DEV AiDevId, HI_S32 s32AiChnCnt,
		HI_BOOL bAnrEn, HI_BOOL bResampleEn)
{
	HI_S32 i;    
	for (i=0; i<s32AiChnCnt; i++)
	{
		if (HI_TRUE == bResampleEn)
		{
			HI_MPI_AI_DisableReSmp(AiDevId, i);
		}
		if (HI_TRUE == bAnrEn)
		{
			HI_MPI_AI_DisableAnr(AiDevId, i);
		}
		HI_MPI_AI_DisableChn(AiDevId, i);
	}  
	HI_MPI_AI_Disable(AiDevId);
	return HI_SUCCESS;
}

/******************************************************************************
 * function : Start Ao
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StartAo(AUDIO_DEV AoDevId, AO_CHN AoChn,
		AIO_ATTR_S *pstAioAttr, AUDIO_RESAMPLE_ATTR_S *pstAoReSmpAttr)
{
	HI_S32 s32Ret;

	s32Ret = HI_MPI_AO_SetPubAttr(AoDevId, pstAioAttr);
	if(HI_SUCCESS != s32Ret)
	{
		printf("%s: HI_MPI_AO_SetPubAttr(%d) failed with %#x!\n", __FUNCTION__, \
				AoDevId,s32Ret);
		return HI_FAILURE;
	}
	s32Ret = HI_MPI_AO_Enable(AoDevId);
	if(HI_SUCCESS != s32Ret)
	{
		printf("%s: HI_MPI_AO_Enable(%d) failed with %#x!\n", __FUNCTION__, \
				AoDevId, s32Ret);
		return HI_FAILURE;
	}
	s32Ret = HI_MPI_AO_EnableChn(AoDevId, AoChn);
	if(HI_SUCCESS != s32Ret)
	{
		printf("%s: HI_MPI_AO_EnableChn(%d) failed with %#x!\n", __FUNCTION__,\
				AoChn, s32Ret);
		return HI_FAILURE;
	}

	if (NULL != pstAoReSmpAttr)
	{
		s32Ret = HI_MPI_AO_DisableReSmp(AoDevId, AoChn);
		s32Ret |= HI_MPI_AO_EnableReSmp(AoDevId, AoChn, pstAoReSmpAttr);
		if(HI_SUCCESS != s32Ret)
		{
			printf("%s: HI_MPI_AO_EnableReSmp(%d,%d) failed with %#x!\n", \
					__FUNCTION__, AoDevId, AoChn, s32Ret);
			return HI_FAILURE;
		}
	}

	//HI_MPI_AO_SetVolume(AoDevId, AoChn, 5); //my sound
	//printf("set vol =>%d\r\n", 5);
	return HI_SUCCESS;
}

/******************************************************************************
 * function : Stop Ao
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StopAo(AUDIO_DEV AoDevId, AO_CHN AoChn, HI_BOOL bResampleEn)
{
	if (HI_TRUE == bResampleEn)
	{
		HI_MPI_AO_DisableReSmp(AoDevId, AoChn);
	}
	HI_MPI_AO_DisableChn(AoDevId, AoChn);
	HI_MPI_AO_Disable(AoDevId);
	return HI_SUCCESS;
}

/******************************************************************************
 * function : Start Aenc
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StartAenc(HI_S32 s32AencChnCnt, PAYLOAD_TYPE_E enType)
{
	AENC_CHN AeChn;
	HI_S32 s32Ret, i;
	AENC_CHN_ATTR_S stAencAttr;

	/* set AENC chn attr */

	stAencAttr.enType = enType;
	stAencAttr.u32BufSize = 30;

	if (PT_ADPCMA == stAencAttr.enType)
	{
		AENC_ATTR_ADPCM_S stAdpcmAenc;
		stAencAttr.pValue       = &stAdpcmAenc;
		stAdpcmAenc.enADPCMType = AUDIO_ADPCM_TYPE;
	}
	else if (PT_G711A == stAencAttr.enType || PT_G711U == stAencAttr.enType)
	{
		AENC_ATTR_G711_S stAencG711;
		stAencAttr.pValue       = &stAencG711;
	}
	else if (PT_G726 == stAencAttr.enType)
	{
		AENC_ATTR_G726_S stAencG726;
		stAencAttr.pValue       = &stAencG726;
		stAencG726.enG726bps    = G726_BPS;
	}
	else if (PT_LPCM == stAencAttr.enType)
	{
		AENC_ATTR_LPCM_S stAencLpcm;
		stAencAttr.pValue = &stAencLpcm;
	}
	else
	{
		printf("%s: invalid aenc payload type:%d\n", __FUNCTION__, stAencAttr.enType);
		return HI_FAILURE;
	}    

	for (i=0; i<s32AencChnCnt; i++)
	{            
		AeChn = i;

		/* create aenc chn*/
		s32Ret = HI_MPI_AENC_CreateChn(AeChn, &stAencAttr);
		if (s32Ret != HI_SUCCESS)
		{
			printf("%s: HI_MPI_AENC_CreateChn(%d) failed with %#x!\n", __FUNCTION__,
					AeChn, s32Ret);
			return HI_FAILURE;
		}        
	}

	return HI_SUCCESS;
}

/******************************************************************************
 * function : Stop Aenc
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StopAenc(HI_S32 s32AencChnCnt)
{
	HI_S32 i;
	for (i=0; i<s32AencChnCnt; i++)
	{
		HI_MPI_AENC_DestroyChn(i);
	}
	return HI_SUCCESS;
}

/******************************************************************************
 * function : Start Adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StartAdec(ADEC_CHN AdChn, PAYLOAD_TYPE_E enType)
{
	HI_S32 s32Ret;
	ADEC_CHN_ATTR_S stAdecAttr;

	stAdecAttr.enType = enType;
	stAdecAttr.u32BufSize = 20;
	stAdecAttr.enMode = ADEC_MODE_STREAM;/* propose use pack mode in your app */

	if (PT_ADPCMA == stAdecAttr.enType)
	{
		ADEC_ATTR_ADPCM_S stAdpcm;
		stAdecAttr.pValue = &stAdpcm;
		stAdpcm.enADPCMType = AUDIO_ADPCM_TYPE ;
	}
	else if (PT_G711A == stAdecAttr.enType || PT_G711U == stAdecAttr.enType)
	{
		ADEC_ATTR_G711_S stAdecG711;
		stAdecAttr.pValue = &stAdecG711;
	}
	else if (PT_G726 == stAdecAttr.enType)
	{
		ADEC_ATTR_G726_S stAdecG726;
		stAdecAttr.pValue = &stAdecG726;
		stAdecG726.enG726bps = G726_BPS ;      
	}
	else if (PT_LPCM == stAdecAttr.enType)
	{
		ADEC_ATTR_LPCM_S stAdecLpcm;
		stAdecAttr.pValue = &stAdecLpcm;
		stAdecAttr.enMode = ADEC_MODE_PACK;/* lpcm must use pack mode */
	}
	else
	{
		printf("%s: invalid aenc payload type:%d\n", __FUNCTION__, stAdecAttr.enType);
		return HI_FAILURE;
	}     

	/* create adec chn*/
	s32Ret = HI_MPI_ADEC_CreateChn(AdChn, &stAdecAttr);
	if (s32Ret)
	{
		printf("%s: HI_MPI_ADEC_CreateChn(%d) failed with %#x!\n", __FUNCTION__,\
				AdChn,s32Ret);
		return s32Ret;
	}
	return 0;
}

/******************************************************************************
 * function : Stop Adec
 ******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StopAdec(ADEC_CHN AdChn)
{
	HI_MPI_ADEC_DestroyChn(AdChn);
	return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif 
#endif /* End of #ifdef __cplusplus */

